import AttributeUtil from '@/AttributeUtil';
import RandomUtil from '@/RandomUtil';
import MathUtil from '@/MathUtil';
import MathCommon from './MathCommon';

const 取属性 = AttributeUtil.getUnitAttribute;

export default class UnitCommon {
    static 取总耐力(目标: unit) {
        let v = 取属性(目标);
        let 耐力 = v?.strength ?? 0;
        耐力 += GetHeroStr(目标, false);
        耐力 += v?.full_property ?? 0;
        耐力 *= 1 + (v?.full_property_p ?? 0) + (v?.strength_p ?? 0);
        return 耐力;
    }

    static 取总力量(目标: unit) {
        let v = 取属性(目标);
        let 力量 = v?.agility ?? 0;
        力量 += GetHeroAgi(目标, false);
        力量 += v?.full_property ?? 0;
        力量 *= 1 + (v?.full_property_p ?? 0) + (v?.agility_p ?? 0);
        return 力量;
    }

    static 取总敏捷(目标: unit) {
        let v = 取属性(目标);
        let 敏捷 = v?.自定义敏捷 ?? 0;
        敏捷 += v?.full_property ?? 0;
        敏捷 *= 1 + (v?.自定义敏捷百分比 ?? 0) + (v?.full_property_p ?? 0);
        return 敏捷;
    }

    static 取总智力(目标: unit) {
        let v = 取属性(目标);
        let 智力 = v?.自定义智力 ?? 0;
        智力 += v?.full_property ?? 0;
        智力 *= 1 + (v?.自定义智力百分比 ?? 0) + (v?.full_property_p ?? 0);
        return 智力;
    }

    static 取总精神(目标: unit) {
        let v = 取属性(目标);
        let 精神 = v?.intelligence ?? 0;
        精神 += GetHeroInt(目标, false);
        精神 += v?.full_property ?? 0;
        精神 *= 1 + (v?.full_property_p ?? 0) + (v?.intelligence_p ?? 0);
        return 精神;
    }

    static getFullProperty(目标: unit) {
        return UnitCommon.取总力量(目标) + UnitCommon.取总敏捷(目标) + UnitCommon.取总智力(目标) + UnitCommon.取总精神(目标) + UnitCommon.取总耐力(目标);
    }

    static 取生命回复(目标: unit) {
        let v = 取属性(目标);
        let val = (GetUnitState(目标, UNIT_STATE_LIFE_REGEN) + (v?.生命恢复 ?? 0) + UnitCommon.取总耐力(目标) * 0.05) * (1 + (v?.生命恢复增强 ?? 0));
        return R2I(val * 100) / 100;
    }

    static 取法力回复(目标: unit) {
        let v = 取属性(目标);
        let val = (GetUnitState(目标, UNIT_STATE_MANA_REGEN) + (v?.法力恢复 ?? 0) + UnitCommon.取总精神(目标) * 0.03) * (1 + (v?.法力恢复增强 ?? 0));
        return R2I(val * 100) / 100;
    }

    static 取总护甲(目标: unit) {
        let v = 取属性(目标);
        return ((v?.基础护甲 ?? 0) + (v?.附加护甲 ?? 0) + UnitCommon.取总耐力(目标) * 0.5) * (1 + (v?.护甲百分比 ?? 0)) ?? 0;
    }

    static 取总魔抗(目标: unit) {
        let v = 取属性(目标);
        return ((v?.基础魔抗 ?? 0) + (v?.附加魔抗 ?? 0) + UnitCommon.取总精神(目标) * 0.5) * (1 + (v?.魔抗百分比 ?? 0)) ?? 0;
    }

    static 取总闪避(目标) {
        let base = 0;
        let v = 取属性(目标);
        if (v != null) {
            base = v?.基础闪避 ?? 0;
        }
        let hero_level = GetHeroLevel(目标);
        if (IsUnitIllusion(目标)) {
            hero_level = (v?.hero_level ?? 0) as number;
        }

        let 敏捷 = UnitCommon.取总敏捷(目标);
        let 敏捷影响 = MathCommon.calulateReduce(敏捷, PHYSICAL_DODGE_PER_AGI, (hero_level + 10) / REDUTION_ATTENUATION);
        base += 敏捷影响;

        if (v != null) {
            for (let key in v) {
                if (key.includes('闪避')) {
                    if (key == '基础闪避') {
                        continue;
                    }
                    if (!v[key]) {
                        continue;
                    }
                    let doge = v[key] as number;
                    if (doge == 0) continue;
                    // 正数和负数的计算方式要区分开
                    if (doge > 0) {
                        // 正数 乘法叠加
                        if (doge > base) {
                            base = doge * (1 + base);
                        } else {
                            base = base * (1 + doge);
                        }
                    } else {
                        // 负数 加法叠加
                        base += doge;
                    }
                }
            }
        }
        return Math.max(0, R2I(base * 100) / 100);
    }

    static 取物理暴击率(目标: unit) {
        let v = 取属性(目标);
        let 敏捷 = UnitCommon.取总敏捷(目标);
        let hero_level = GetHeroLevel(目标);
        if (IsUnitIllusion(目标)) {
            hero_level = (v?.hero_level ?? 0) as number;
        }
        let 敏捷影响 = MathCommon.calulateReduce(敏捷, 0.02, (hero_level + 10) / REDUTION_ATTENUATION);
        let 暴击 = v?.物理暴击机率 ?? 0;
        暴击 = R2I((敏捷影响 + 暴击) * 10000) / 10000;
        return Math.max(0, 暴击);
    }

    static 取法术暴击率(目标: unit) {
        let v = 取属性(目标);
        let 智力 = UnitCommon.取总智力(目标);
        let hero_level = GetHeroLevel(目标);
        if (IsUnitIllusion(目标)) {
            hero_level = (v?.hero_level ?? 0) as number;
        }
        let 智力影响 = MathCommon.calulateReduce(智力, 0.02, (hero_level + 10) / REDUTION_ATTENUATION);
        let 暴击 = v?.法术暴击机率 ?? 0;
        暴击 = R2I((智力影响 + 暴击) * 10000) / 10000;
        return Math.max(0, 暴击);
    }

    static 取物理暴击伤害(目标) {
        let v = 取属性(目标);
        let 力量 = UnitCommon.取总力量(目标);
        let 力量影响 = 力量 * PHYSICAL_CRITICAL_DAMAGE_PER_STR;
        let 伤害 = (v?.物理暴击伤害 ?? 0) + 1.5;
        return R2I((力量影响 + 伤害) * 100) / 100;
    }

    static 取法术暴击伤害(目标) {
        let v = 取属性(目标);
        let 智力 = UnitCommon.取总智力(目标);
        let 智力影响 = 智力 * MAGIC_CRITICAL_DAMAGE_PER_INT;
        let 伤害 = (v?.法术暴击伤害 ?? 0) + 1.5;
        return R2I((智力影响 + 伤害) * 100) / 100;
    }

    static 取物理伤害增强(目标: unit) {
        let v = 取属性(目标);
        let base = 1;
        base += v?.物理伤害倍率 ?? 0;
        return R2I(base * 100) / 100;
    }

    static 取法术伤害增强(目标: unit) {
        let v = 取属性(目标);
        let base = 1;
        base += v?.法术伤害倍率 ?? 0;
        return R2I(base * 100) / 100;
    }

    static 取法强(目标: unit) {
        let v = 取属性(目标);
        let base = 0;
        base += ((v?.法术强度 ?? 0) + UnitCommon.取总智力(目标) * 0.5) * (1 + (v?.法术强度百分比 ?? 0));
        return R2I(base);
    }

    static 取攻击(目标: unit) {
        return RandomUtil.nextReal(GetUnitState(目标, UnitStateDamageMix), GetUnitState(目标, UnitStateDamageMax));
    }

    static 取固定攻击(目标: unit) {
        let atk = (GetUnitState(目标, UnitStateDamageMix) + GetUnitState(目标, UnitStateDamageMax)) / 2;
        return R2I(atk);
    }

    static 取物理伤害减免(目标: unit) {
        let v = 取属性(目标);
        let base = 0;
        base += v?.物理伤害减免 ?? 0;
        return R2I(base * 100) / 100;
    }

    static 取法术伤害减免(目标: unit) {
        let v = 取属性(目标);
        let base = 0;
        base += v?.法术伤害减免 ?? 0;
        return R2I(base * 100) / 100;
    }

    static 取命中率(目标: unit) {
        let v = 取属性(目标);
        return 1 + (v?.命中 ?? 0);
    }

    static 取物理吸血(目标: unit) {
        let v = 取属性(目标);
        return v?.物理吸血 ?? 0;
    }

    static 取法术吸血(目标: unit) {
        let v = 取属性(目标);
        return v?.法术吸血 ?? 0;
    }

    static 取冷却降低(目标: unit) {
        let v = 取属性(目标);
        let base = 1;
        if (v != null) {
            for (let key in v) {
                if (key.includes('冷却') && typeof v[key] == 'number') {
                    base *= 1 - (v[key] as number);
                }
            }
        }
        return MathUtil.clamp(R2I(base * 100) / 100, 0, 1);
    }

    static 取AOE伤害减免(目标: unit) {
        let v = 取属性(目标);
        return v?.AOE伤害减免 ?? 0;
    }

    static 取治疗增强(目标: unit) {
        let v = 取属性(目标);
        return v?.治疗增强 ?? 0;
    }

    static 取总移动速度(目标: unit) {
        return Math.max(0, R2I(db.getUnitSolarData(目标)?._sl_logical_MoveSpeed ?? GetUnitMoveSpeed(目标)));
    }

    static 取反伤倍率(目标: unit) {
        let v = 取属性(目标);
        return 1 + (v?.反射伤害倍率 ?? 0);
    }

    static 是否精英单位(u: unit) {
        let atr = AttributeUtil.getUnitTypeAttribute(id2string(GetUnitTypeId(u)));
        return atr?.精英标记;
    }
    static 取持续伤害增强(u: unit) {
        let v = 取属性(u);
        return v?.持续伤害增强 ?? 0;
    }
    static 取持续治疗增强(u: unit) {
        let v = 取属性(u);
        return v?.持续治疗增强 ?? 0;
    }
    static 添加全属性(u: unit, val: number) {
        AttributeUtil.addUnitAttribute(u, {
            full_property: val,
        });
    }

    static 普攻冷却(u: unit) {
        DzAttackAbilityEndCooldown(DzGetAttackAbility(u));
    }
}
